/****************************************************************************
 * Chariott - Continuous Integration Testing Tool
 * Zaid Mohsin
 * The University of York
 * 2012/2013
 * MSc in Information Technology
 * All rights reserved.
 ****************************************************************************/
package chariott.main;

import java.io.File;
import java.io.FileInputStream;

import chariott.configuration.Globals;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.ChannelSftp;

/**
 * SSH Connector is the class that deals with SSH connections to the cloud
 * nodes, sending of the generated scripts through SFTP and execute the console
 * commands to run the files
 * 
 * @author Zaid
 * 
 */
public class SSHConnector {

	private JSch jsch;

	public SSHConnector() {
		try {
			jsch = new JSch();
			jsch.addIdentity(Globals.SSH_PEM_FILE);
			jsch.setConfig("StrictHostKeyChecking", "no");
		} catch (JSchException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
	}

	/**
	 * executes the console commands required to run the Ant Scripts
	 * 
	 * @param session
	 *            the session to access its console
	 * @param antScript
	 *            the ant script to be executed
	 */
	private void executeCommands(Session session, String antScript) {
		try {

			Channel channel = session.openChannel("exec");
			((ChannelExec) channel)
					.setCommand("nohup ant -logger org.apache.tools.ant.listener.ProfileLogger -buildfile "
							+ antScript
							+ " all </dev/null 1>stdout.log 2>stderr.log &");
			// channel.setInputStream(null);

			((ChannelExec) channel).setErrStream(System.err);
			((ChannelExec) channel).setPty(true);
			((ChannelExec) channel).setPtySize(100, 100, 100, 100);

			// InputStream in = channel.getInputStream();

			Main.logger.info("Running: " + antScript);
			channel.connect();

			channel.disconnect();

		} catch (Exception e) {
			System.out.println(e);
		}
	}

	/**
	 * Method sends files to a specific session using SFTP protocol
	 * 
	 * @param myFile
	 *            the file to send
	 * @param session
	 *            the session to send that file to
	 */
	private void sendFile(File myFile, Session session) {

		ChannelSftp channelSftp = null;
		Channel channel = null;

		try {

			channel = session.openChannel("sftp");
			channel.connect();
			channelSftp = (ChannelSftp) channel;

			File f = myFile;

			channelSftp.put(new FileInputStream(f), f.getName());

		} catch (Exception ex) {

			ex.printStackTrace();

		}
	}

	/**
	 * create an SSH session based on the client connection to the hostname
	 * provided.
	 * 
	 * @param hostname
	 *            ip address or public dns of the host to connect to
	 * @return
	 */
	private Session connectSession(String hostname) {
		Session session = null;
		try {
			session = jsch.getSession(Globals.SSH_SESSION_USER, hostname, 22);

			session.connect(1000000000); // making a connection with timeout.

			Main.logger.info("Connected to: " + session.getHost());

		} catch (JSchException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return session;
	}

	/**
	 * connects to the hostname sends the script file , and execute the commands
	 * to run the file.
	 * 
	 * @param hostname
	 * @param scriptFile
	 */
	public void executeSequence(String hostname, File scriptFile) {
		Session mySession = connectSession(hostname);
		sendFile(scriptFile, mySession);
		executeCommands(mySession, scriptFile.getName());
		mySession.disconnect();
	}
}
